Repository navigation
Conversation
Move the passive helper and Umami adapter into one product source, retain the existing assertions, and add consent-aware lazy lifecycle control. Refs iflytek#989 Signed-off-by: 千乘妍 (Xiaoyaner) <258399167+xiaoyaner0201@users.noreply.github.com>
Safely transport bounded JSON using existing image tools, generate isolated exact proxy routes with verified HTTPS, and wire Compose and Helm with closed defaults. Refs iflytek#989 Signed-off-by: 千乘妍 (Xiaoyaner) <258399167+xiaoyaner0201@users.noreply.github.com>
Replace manual injection instructions with Compose, Docker and Helm configuration, explicit platform initialization, consent controls, privacy boundaries and verified task status. Refs iflytek#989 Signed-off-by: 千乘妍 (Xiaoyaner) <258399167+xiaoyaner0201@users.noreply.github.com>
Clarify the one-time initialization sequence verified during the guide walkthrough. Refs iflytek#989 Signed-off-by: 千乘妍 (Xiaoyaner) <258399167+xiaoyaner0201@users.noreply.github.com>
Helm --set-string parses {...} as a list, so the enabled-analytics
contract case failed schema validation in CI. Use a values file, the
same way the operator guide documents the setting.
Refs iflytek#989
Signed-off-by: 千乘妍 (Xiaoyaner) <258399167+xiaoyaner0201@users.noreply.github.com>
|
我们基于当前提交 本次使用源码构建的真实镜像、真实 SkillHub 后端和 Umami 验证了:
这些主要链路均通过,暂未发现阻断性的浏览器或代理运行问题。建议本 PR 再调整以下两部分: 1. 隔离 Helm 统计配置的影响 目前统计字段放在共享 ConfigMap 中,而后端 Pod 的 checksum 覆盖整份 ConfigMap。因此仅修改统计开关、规则、网站 UUID 或上游地址,也会触发后端 Pod 替换;部分存储配置使用 我们已通过 Helm 模板渲染对照确认。建议将统计配置拆到 Web 专用 ConfigMap,或收窄后端 checksum 的输入范围,并补测试:只改统计配置时,仅 Web 更新;修改后端配置时,后端仍正常更新。无需为此大范围重构 Chart。 2. 对齐文档与验收记录
一键部署增强可以另开 PR,不要求本次完成。 建议后续在现有
已有统计平台的部署方跳过第一步。文档说明网络连通、密钥复用、升级和备份即可,不必为了“一键”增加自动创建网站的逻辑。 当前 PR 保留现有配置化接入和可选 Compose 方式即可。完成上述 Helm 隔离和文档调整后,我们再核验受影响部分。 |
|
感谢细致的核验,两部分都已按建议调整,新 head 是 1. Helm 统计配置隔离 统计的两个值从共享 ConfigMap 移到 Web 专用的
在旧模板上跑这组测试会失败;我也试过把统计值同时留在共享 ConfigMap,测试同样会拦下。 2. 文档与验收记录
一键部署按你们的建议另开 PR。辛苦再核验一下受影响的部分。 |
Move analytics values into a Web-only ConfigMap. The server checksum hashes the shared ConfigMap, so analytics-only changes used to replace server pods. Contract tests render before/after values and assert that analytics-only changes roll only Web while backend changes still roll the server. Docs: Compose restart does not re-read .env.release, old tabs keep the old config, a valid but unknown Umami website returns 400 and stores nothing, and new adapters also need deploy-side validation, proxy endpoints and tests. OpenSpec now separates executed Helm template checks from the real-cluster verification that has not been run. Signed-off-by: 千乘妍 (Xiaoyaner) <258399167+xiaoyaner0201@users.noreply.github.com>
47285e4 to
f8ab71e
Compare
Refs iflytek#989 Signed-off-by: 千乘妍 (Xiaoyaner) <258399167+xiaoyaner0201@users.noreply.github.com>
Refs iflytek#989 Signed-off-by: 千乘妍 (Xiaoyaner) <258399167+xiaoyaner0201@users.noreply.github.com>
crypto.randomUUID only exists in secure contexts and newer browsers, so fresh browsers on plain-HTTP intranet deployments dropped every event. Fall back to a getRandomValues v4 UUID with the same format. Refs iflytek#989 Signed-off-by: 千乘妍 (Xiaoyaner) <258399167+xiaoyaner0201@users.noreply.github.com>
|
我们对当前 PR 做了源码 Review 和本地真实部署验证。配置开启后的事件能够进入 Umami,关闭采集、错误配置、统计服务故障、停止采集及根路径/子路径等场景也进行了核验,目前没有发现新的阻断级运行问题。 前面 Review 提到的“修改统计配置连带触发后端滚动更新”,已经通过 Web 专用 ConfigMap 解决,模板对照验证也已通过。 继续梳理生产部署后,主要还有以下需要补齐的内容。 1. 一键部署用户的接入链路还不完整目前 建议沿用现有脚本入口,提供两步部署:
已有统计平台的部署方直接填写地址和 UUID,跳过第一步。无需修改 JS、Nginx,也不要求克隆源码。 2. 统计平台与 SkillHub 分开管理当前可选 Compose 文件是叠加到同一个项目里的。建议调整为两个独立 Compose 项目:
这样统计平台可以单独维护,SkillHub 仍按原有方式部署和升级。 3. Helm 提供对应的独立部署路径当前 SkillHub Chart 已支持配置统计地址和 UUID,但不负责安装 Umami。 建议保持两个独立 Release:统计平台与 SkillHub 分别部署,通过 Kubernetes Service/DNS 连接;不把 Umami 作为 SkillHub 的强制依赖。 如果提供自建统计平台的 Helm 部署,需要补齐独立部署配套,说明 Secret、持久化、管理入口及升级方式。已有平台的用户只需配置 SkillHub values。 验证方面,已有真实集群的基础安装/升级记录,但不能代替本次开启采集后的集群验证;仍需补测实际采集,以及仅修改统计配置时只滚动 Web。 4. 文档与验收同步补齐建议文档按三条路径分别说明:
重点说明文件如何获取、UUID 在哪一步取得、配置如何生效,以及关闭、升级和数据保留方式。运行边界也请保留:旧标签页需刷新才能使用新配置;统计故障期间的事件不保证补发;格式正确但填错 UUID 仍可能无法采集。 新增部署流程请覆盖:空目录安装、已有实例接入、重复执行、容器重建后网络与数据保留、统计独立启停,以及关闭采集后的业务回归。 另外有一项非阻断的维护建议:部分测试仍断言旧 PR 的静态配置 fixture,可以考虑把仍需保留的约束迁到当前生产配置测试中,再清理重复 fixture。 整体采集架构可以沿用,主要是补齐部署交付闭环。这部分可以拆成后续 PR,但希望明确交付范围与跟踪事项,避免文档把当前能力描述为完整的一键接入。 以上是结合本地验证提出的建议。如果你有更简单、维护成本更低的实现方式,也欢迎讨论;核心目标是配置化接入、部署方便,并控制对现有 SkillHub 的影响。 |
Signed-off-by: 千乘妍 (Xiaoyaner) <258399167+xiaoyaner0201@users.noreply.github.com>
Signed-off-by: 千乘妍 (Xiaoyaner) <258399167+xiaoyaner0201@users.noreply.github.com>
|
感谢这轮细致的部署验证 🙏 建议我们都认同。想把范围拆一下,方便本 PR 先收口: 本 PR(#1037)
后续 PR:一键部署闭环 按你们的四点建议单独交付:
这些会写进 OpenSpec 任务作为跟踪项。这样拆可以吗? |
Signed-off-by: 千乘妍 (Xiaoyaner) <258399167+xiaoyaner0201@users.noreply.github.com>
Signed-off-by: 千乘妍 (Xiaoyaner) <258399167+xiaoyaner0201@users.noreply.github.com>
Signed-off-by: 千乘妍 (Xiaoyaner) <258399167+xiaoyaner0201@users.noreply.github.com>
Signed-off-by: 千乘妍 (Xiaoyaner) <258399167+xiaoyaner0201@users.noreply.github.com>
Signed-off-by: 千乘妍 (Xiaoyaner) <258399167+xiaoyaner0201@users.noreply.github.com>
Signed-off-by: 千乘妍 (Xiaoyaner) <258399167+xiaoyaner0201@users.noreply.github.com>
Signed-off-by: 千乘妍 (Xiaoyaner) <258399167+xiaoyaner0201@users.noreply.github.com>
Signed-off-by: 千乘妍 (Xiaoyaner) <258399167+xiaoyaner0201@users.noreply.github.com>
Signed-off-by: 千乘妍 (Xiaoyaner) <258399167+xiaoyaner0201@users.noreply.github.com>
Signed-off-by: 千乘妍 (Xiaoyaner) <258399167+xiaoyaner0201@users.noreply.github.com>
Both raw bases publish compose.analytics-umami.yml at the root, so the Aliyun and GitHub branches fetched the same path. No behavior change. Signed-off-by: 千乘妍 (Xiaoyaner) <258399167+xiaoyaner0201@users.noreply.github.com>
|
@XiaoSeS 部署闭环已经按四点建议在本 PR 补齐,按步骤拆成了多个提交方便逐个看。当前 head 是 1. 一键部署两步接入
不需要克隆源码,也不用改 JS 或 Nginx。 2. 独立管理
3. Kubernetes
4. 文档和验收 文档按三条路径分别说明。以下场景都在本机真实运行过:
kind 集群中,Umami 部署在独立 namespace,SkillHub 是单独的 Release。开启采集后事件确实写入了 Umami 数据库;只改统计配置时只有 Web Pod 被替换,Server Pod UID 不变。脚本在 旧 fixture 测试已改为断言当前生产配置。 需要说明的两点
详细结果见 PR 正文。辛苦再核验一下 🙏 |
|
补充一条 DataFinder 的真实平台验收(head 我们用本分支
平台事件列表的元数据通常会延迟一段时间出现,入库统计确认后我会再补充在这里。 |
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
Summary
Refs #989(两步交付的第二步。合并并验证后,可以关闭 #989)
按 #1010 合并时的约定和 OpenSpec
openspec/changes/add-configurable-frontend-analytics/里的 PR-2 部分,把前端动作统计做成「改配置就能开」的可选功能。SKILLHUB_WEB_ANALYTICS_CONFIG(JSON:enabled、adapter、consent、rules、adapterConfig)和SKILLHUB_WEB_ANALYTICS_UPSTREAM(统计平台地址,只在部署侧使用,不会下发到浏览器)。不需要改 JS、复制文件或手写 Nginx。enabled:false、consent:denied或配置写错时,不加载采集模块和 SDK,也不发请求;页面启动不等待统计平台。web/src/features/analytics/(通用类型、controller、loader、静态注册表、adapters/umami)。feat(web): add passive semantic analytics attributes across frontend workflows #1010 的两组测试一起迁入,断言没有改动。通用部分不认识 Umami 的字段,以后加平台只需新增一个注册的 adapter。/_skillhub-analytics/代理。只放行 Umami 的script.js和api/send,其他路径都返回 404,不暴露管理界面。HTTPS 上游会校验证书并带正确的 SNI;代理会去掉 Cookie、Authorization、Referer。保留前缀已同步到20-base-path.sh、base-path-config.ts、validate-release-config.sh和 Helm 校验。子路径部署可用。runtime-config.js,浏览器端按数据解析。代价是多了一个约 90 行、有测试覆盖的小解析器。compose.release.yml、.env.release.example和 Helm 的 values、schema、ConfigMap、Deployment 都已透传,默认关闭。新增可选的compose.analytics-umami.yml,用来自托管 Umami 和它自己的 Postgres:必须显式提供密码,管理端口只绑本机,不额外增加 Nginx。docs/frontend-analytics-integration.md改写成只改配置的中文接入指南,内容包括已有 Umami、自托管组合、动态授权、验收、排障、升级和关闭;docs/frontend-analytics.md更新为英文契约。docs/examples/analytics/只保留一个指路说明。OpenSpectasks.md只勾选了本 PR 实际完成的项目。第二个平台:DataFinder(火山引擎增长分析)
原在 #1050,按讨论合入本 PR(#1050 已关闭)。它和 Umami 共用同一套转换层、开关和代理框架,不涉及一键部署。
adapter: "datafinder",adapterConfig只接受数字appId和可选的product(默认skillhub),upstream 填采集域名。其他字段全部拒绝,包括 App Key,防止误把服务端密钥放进前端。fetch(keepalive)发 DataFinder Web 上报的最小/list负载:一个 batch、一个事件。不批量等待,不持久化,不重试,每次最长 3 秒。skill.download.request),params只含原生event。公共属性只有product和module:module是动作所在页面的路由模板(例如/space/$namespace/$slug),不含真实 namespace、slug、query 或 hash,未匹配的页面记为other。user_unique_id/web_id,存在 localStorage,用于按浏览器统计 UV。不绑定 SkillHub 账号。纯 HTTP 内网部署没有crypto.randomUUID,改用getRandomValues生成。存储不可用时只在当前页用内存 ID。文档写明这不等于无身份数据,由部署方评估。e:0且sc:1;HTTP 200 不算成功。POST /_skillhub-analytics/list,Umami 的端点返回 404。沿用 TLS 校验,并清除 Cookie、Authorization、Referer。保留浏览器 User-Agent,因为平台会拒收非浏览器 UA。currentPageTypegetter,依次经 loader、controller 传给 factory。Umami 不使用它。通用配置和 controller 不认识 DataFinder 的字段。awk 校验器增加数字值和按适配器分支。sc:0、502)和隐私边界;英文契约和 OpenSpec PR-3 任务同步更新。一键部署与独立管理(维护者第二轮反馈)
runtime.sh两步部署:analytics-up自动获取compose.analytics-umami.yml,首次生成并保存独立密钥(<home>/analytics/.env,600 权限,已存在不覆盖),启动 Umami 和它自己的 Postgres,输出管理地址。用户改密、建网站拿到 UUID 后,运行analytics-enable --website-id <UUID>:写入配置,Web 加入共享网络并重新创建。已有平台用analytics-enable --website-id <UUID> --upstream <origin>,跳过第一步,也不建网络;DataFinder 用--adapter datafinder --app-id <N> --upstream <origin>。另有analytics-disable、analytics-down(只停止,不删卷)和analytics-ps/logs/pull。compose.release.analytics.yml)和 Umami 加入外部网络skillhub-analytics,网络由脚本幂等创建、由 Compose 声明。开启后普通up自动带上这层网络配置,Web 重建后仍然连接。clean保留统计平台的密钥和文件。deploy/k8s/analytics-umami/umami.yaml在独立 namespace 中部署 Postgres(PVC)、Umami 和两个 ClusterIP Service,Secret 由部署方创建。SkillHub Chart 只填写web.analytics,经 Service DNS 连接,不依赖 Umami。charts/skillhub/tests/analytics-smoke.sh核对事件真实入库,并断言只改统计配置时 Web Pod 替换、Server Pod UID 不变。pr1-compose.yaml、pr1-nginx.conf)已删除,仍需要的约束改为断言当前生产配置。新增scripts/tests/runtime-analytics-test.sh,已加入 CI。--aliyun:该模式从 OSS 根目录下载文件。OSS 目前没有新增的两个 Compose 文件(实测 404),需要在发布时同步上传,文档已写明。Validation
基于最新 main(已合并
a681e43e之后的 main),headffc9c834。一键部署实测(本机真实 Docker,隔离项目名和端口):
runtime.sh up后 Web 健康和业务 API 均为 200;analytics-up、建网站、analytics-enable后,经同源代理发送事件 200,Umami API 和数据库都查到入库。analytics-up/up前后密钥哈希、server 容器和事件数都不变。--force-recreate后,默认网络和共享网络都还在,已存事件不变。analytics-down时业务健康 200;再analytics-up,数据还在。analytics-disable后采集路由 404,业务 API 200。--upstream接入后事件数 1 → 2,Web 没有加入本地统计网络。真实集群(kind): Umami/Postgres 部署在独立
statsnamespace,SkillHub 是单独的 Helm Release。analytics-smoke.sh结果:代理发送 200,Umami 数据库事件数 3 → 4。只改统计配置的helm upgrade替换了 Web Pod,Server Pod UID 不变。限制:
could not compute MD5 hash: unsupported,这与本 PR 无关。集群验收改用独立的官方 postgres:16 +externalDatabase,所以不能说明固定镜像这条路径已通过。另外做了本地真实运行验收:用本 PR 构建的前端、仓库里的 Nginx 模板和启动脚本,配合 Umami 3.4.1 与 Postgres,在真实 Chrome 中完成 26 项检查,Umami 实际入库 9 条事件。检查覆盖:
stop()后不再发送/skillhub/子路径部署SkillHub 后端 API 是合成响应,不能作为后端业务的端到端证明。
还没覆盖的部分:
Risk
/_skillhub-analytics/成为保留前缀,SKILLHUB_WEB_BASE_PATH不能以它开头。修改配置后需要重新创建 Web(Compose 用up -d --force-recreate web,restart不会重新注入环境变量),新打开的页面才会生效;已经打开的旧标签页不会因关闭配置立即停止,需要刷新或关闭。Helm 的统计值放在 Web 专用 ConfigMap,只改统计配置时仅 Web 滚动更新,后端 Pod 不替换。SKILLHUB_WEB_ANALYTICS_CONFIG并重新创建 Web,新页面即完全关闭;回退镜像版本也可以。Notes
api/send返回400 Website not found,事件不入库。排障表已补充。docs/frontend-analytics-integration.md、docs/frontend-analytics.md、docs/09-deployment.md和 chart README 的入口链接。English
Also included: the DataFinder (Volcengine growth analytics) adapter from #1050 (now closed). Config accepts only a numeric
appIdand optionalproduct; no official SDK, a boundedfetchto a POST-only/_skillhub-analytics/listproxy; success requirese:0/sc:1; anonymous browser UUID; route templates only. Also adds one-click deployment:runtime.sh analytics-up/analytics-enable(independent Compose projects sharing one external network; secrets generated once and preserved), an independent Kubernetes Umami unit, three documented paths, and fixture cleanup. Verified with real Docker Compose scenarios and a kind cluster (event stored; analytics-only upgrade rolls only Web).Refs #989 (second step; #989 can be closed once this is merged and verified).
Implements the PR-2 part of
openspec/changes/add-configurable-frontend-analytics/, as agreed when #1010 was merged:SKILLHUB_WEB_ANALYTICS_CONFIG(JSON:enabled,adapter,consent,rules,adapterConfig) andSKILLHUB_WEB_ANALYTICS_UPSTREAM(deploy-side origin, never sent to the browser) through Docker/Compose or Helm. No JS, file copying or hand-written Nginx.enabled:false,consent:deniedor invalid config means no analytics chunk, no SDK and no request. App startup never waits on the collector.web/src/features/analytics/(types, controller, loader, static registry,adapters/umami). Both feat(web): add passive semantic analytics attributes across frontend workflows #1010 test suites moved with their assertions unchanged. Generic code has no Umami fields, and new platforms are added as registered adapters.script.jsandapi/sendare proxied under/_skillhub-analytics/; all other paths return 404. HTTPS upstreams are verified with correct SNI, and Cookie, Authorization and Referer are stripped. The reserved prefix is synced across the base-path checks and Helm validation, and sub-path deployment works.runtime-config.js, where the browser parses it as data. The trade-off is a small, tested parser of about 90 lines..env.release.exampleand Helm values, schema, ConfigMap and Deployment pass the config through, with analytics off by default. The optionalcompose.analytics-umami.ymloverlay self-hosts Umami and its own Postgres, requires explicit secrets, binds the admin port to loopback only and adds no extra Nginx.docs/examples/analytics/is now a pointer only. OpenSpec ticks cover only the work done in this PR.Validation at head
ffc9c834merged with latest main:unbound variablefrom forwarded-proto also appears on main.helm lint --strictandconfiguration-contracts.shpass (helm 3.19.0 container). Analytics lives in a Web-only ConfigMap; the contract test asserts analytics-only changes roll only Web and backend changes still roll the server. These are template checks; no real-cluster install was run.A local real-runtime run (this PR's dist with the repo's Nginx template and entrypoints, plus Umami 3.4.1, Postgres and real Chrome) passed 26 checks, with 9 events stored. Covered: default zero requests, enabled loading, allowlisted payload, invalid config, DNS failure and collector downtime isolation, 404 for unregistered paths,
stop(),/skillhub/sub-path and a 5 MiB upload. SkillHub API responses were synthetic.Not run locally:
Rollback: clear
SKILLHUB_WEB_ANALYTICS_CONFIGand recreate Web (docker compose restartdoes not re-read the env file). Old tabs keep collecting until reloaded or closed.Notes: new platforms need a registered adapter plus deploy-side validation, proxy endpoints and tests. A valid UUID for a website that does not exist in Umami gets
400 Website not foundand stores nothing; passing config validation does not prove collection.